var express = require('express');
var multiparty = require('multiparty');
var websocket = require('socket.io');
var EventEmitter = require('events');
var util = require('util');

var path = require('path');
var fs = require('fs');
var app = express();
var _ = require('lodash');

var bodyParser = require('body-parser');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: false}));

app.use('/static',express.static(path.join(__dirname,'public')));

app.get('/watcher/query/*',(req,res,next)=>{
    var name = req.params[0];
    if(name)
        res.json({
            ipaddress:parasMap[name].ipaddress,
            env:parasMap[name].env
        });
    else{
        res.json(_.map(parasMap,(v,k)=>{ return {name:k,env:v.env,ipaddress:v.ipaddress}}))
    }
})
/**
 * disk operator
 */
app.get('/watcher/:p/disk/*',(req,res,next)=>{
    var p = req.params.p;
    if(!parasMap[p]) next('paras not found!');
    else{
//        parasMap['shenlinjie@WIN-778R5O2CT99'].skt.emit('disk',req.params[0]);
        parasMap[p].skt.emit('disk',req.params[0]);
        parasMap[p].event.once('disk-result',(ret)=>{
            ret.stream.pipe(res);
        })
    }
});
app.post('/watcher/:p/disk/*',(req,res,next)=>{
    var p = req.params.p;
    if(!parasMap[p]) next('paras not found!');
    else{
        try{
            var form = new multiparty.Form();
            form.parse(req);
            form.on('error', (err)=>{
                next(err);
            })
            form.on('part',(part)=>{
                if(part.filename){
                    parasMap[p].event.emit('disk-uploadfile',{stream:part,name:part.filename,dir:req.params[0]});
                     parasMap[p].event.once('disk-uploadfile-result',(err,msg)=>{
                        if(err) next(err)
                        else res.json({status:0,result:msg}); 
                    })
                }
            })
            //todo:多文件支持
            // form.on('close', function() {
            //     console.log('Upload completed!');
            //     parasMap[p].event.once('disk-uploadfile-result',(err,msg)=>{
            //         if(err) next(err)
            //         else res.json({status:0,result:msg}); 
            //     })
            // });
        }catch(e){
            next(e);
        }
    }
});
app.delete('/watcher/:p/disk/*',(req,res,next)=>{
    var p = req.params.p;
    if(!parasMap[p]) next('paras not found!');
    else{
        parasMap[p].skt.emit('rem',req.params[0]);
        next();
    }
});
/**
 * screen operator
 */
app.get('/watcher/:p/screen',(req,res,next)=>{
    var p = req.params.p;
    if(!parasMap[p]) next('paras not found!');
    else{
        parasMap[p].skt.emit('screen',req.params[0]);
        parasMap[p].event.once('screen-result',(ret)=>{
            ret.stream.pipe(res);
        })
    }
});
/**
 * eval operator
 *(exec('notepad.exe',(err,stdout,stderr)=>{}))
 *  (exec('tasklist', (err, stdout, stderr)=>{
 *       if(err){ return console.log(err); }
 *       var found = false;
 *       stdout.split('\n').filter((line)=>{
 *          var p=line.trim().split(/\s+/),pname=p[0],pid=p[1];
 *          if(pname.toLowerCase().indexOf('notepad.exe')>=0 && parseInt(pid))
 *          {
 *                  found = true;
 *                  console.log(pname,pid);
 *                  exec('taskkill /F /pid '+pid,(err, stdout, stderr)=>{ });
 *          }         
 *      });
 * }))
if exist k.ll (for /f "tokens=2 delims=," %%i in ('tasklist /fo csv /fi "imagename eq Client.exe" /nh') do taskkill /F /pid %%i&echo %%i %t%)
if exist k.ll (for /f "tokens=2 delims=," %%i in ('tasklist /fo csv /fi "imagename eq WuXia.exe" /nh') do taskkill /F /pid %%i&echo %%i %t%)
if exist k.ll (for /f "tokens=2 delims=," %%i in ('tasklist /fo csv /fi "imagename eq WuXia_Client.exe" /nh') do taskkill /F /pid %%i&echo %%i %t%)
 */
app.post('/watcher/:p/eval',(req,res,next)=>{
    var p = req.params.p;
    if(!parasMap[p]) next('paras not found!');
    else{
        parasMap[p].skt.emit('eval',req.body.scriptStr)
        parasMap[p].event.once('eval-result',(err,result)=>{
            if(err) next(err);
            else res.end(ret);
        });
    }
});

app.get('/watcher/:p/kill/:tname',(req,res,next)=>{
    var p = req.params.p;
    var tname = req.params.tname;
    if(!parasMap[p]) next('paras not found!');
    else{
	parasMap[p].skt.emit('eval',`(exec('tasklist', function(err, stdout, stderr) {  if(err){ return console.log(err); }  var found = false; stdout.split('\\n').filter(function(line){ var p=line.trim().split(/\\s+/),pname=p[0],pid=p[1]; if(pname.toLowerCase().indexOf('${tname}')>=0 && parseInt(pid)){ found = true; console.log(pname,pid); exec('taskkill /F /pid '+pid,function(err, stdout, stderr){ if(err){ return console.log('失败！！');	} console.log('${tname}被成功杀掉！');});}}); if(!found) console.log('没发现${tname}');}))`);
        parasMap[p].event.once('eval-result',(err,result)=>{
            if(err) next(err);
            else res.end(ret);
        });
    }
});

var server = app.listen(13527);
/**
 * websocket 
 * connect to moles
 */
var ioMole = websocket.listen(server).of('/mole');
var ss = require('socket.io-stream');

var parasMap = {};
ioMole.on('connection',(skt)=>{
    var sktEvent = new EventEmitter()
    skt.emit('init',(name,env)=>{
        parasMap[name] = {
            ipaddress:skt.conn.remoteAddress,
            env,
            skt,
            event:sktEvent
        }
        skt.name = name;
    });
    skt.on('echo',(msg)=>{        console.log(msg);        process.emit('echo',msg);    });
    skt.on('eval',(err,result)=>{
        sktEvent.emit('eval-result',err,{from:skt.name,result});
    });
    // skt.emit('eval',st,(err,result)=>{
    //     sktEvent.emit('eval-result',err,result);
    // });
    ss(skt).on('disk',(stream,dir)=>{
        sktEvent.emit('disk-result',{from:skt.name,stream});
    });
    ss(skt).on('screen',(stream,dir)=>{
        sktEvent.emit('screen-result',{from:skt.name,stream});
    });
    
    sktEvent.on('disk-uploadfile',(file)=>{
        var stream = ss.createStream();
        ss(skt).emit('disk-uploadfile',stream,file.dir,file.name,(err,msg)=>{
            sktEvent.emit('disk-uploadfile-result',err,msg);
        });
        file.stream.pipe(stream);
    })
});